﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using System.IO;
using System.Threading;


using System.Windows.Forms;

using System.Speech.Recognition;

using System.Diagnostics;

namespace test
{
    class microphone:Form
    {
        #region  recording settings

            static int    AUDIO_LENGTH_SEC = 4;
            static string TMP_WAVFILENAME  = @"C:\a.wav";
            static string TMP_FLACFILENAME = @"C:\a.flac";        
            static string LANGUAGE         = "pl";

        #endregion
            private Button button5;
            private Label label3;
            private Label label2;
            private ComboBox comboBox1;
            private Label label1;
            private GroupBox groupBox1;

        //recording,converting audio
        SOX sox;


        #region FORM - AUTOGENERATED
        public microphone()
        {
            InitializeComponent();
        }
        private TextBox textBox4;
        private TreeView treeView1;
        private System.ComponentModel.IContainer components;
        private TextBox textBox3;
        private GroupBox groupBox2;
        private void InitializeComponent()
        {
            this.button5 = new System.Windows.Forms.Button();
            this.textBox3 = new System.Windows.Forms.TextBox();
            this.groupBox2 = new System.Windows.Forms.GroupBox();
            this.label3 = new System.Windows.Forms.Label();
            this.label2 = new System.Windows.Forms.Label();
            this.treeView1 = new System.Windows.Forms.TreeView();
            this.textBox4 = new System.Windows.Forms.TextBox();
            this.comboBox1 = new System.Windows.Forms.ComboBox();
            this.label1 = new System.Windows.Forms.Label();
            this.groupBox1 = new System.Windows.Forms.GroupBox();
            this.groupBox2.SuspendLayout();
            this.groupBox1.SuspendLayout();
            this.SuspendLayout();
            // 
            // button5
            // 
            this.button5.Location = new System.Drawing.Point(15, 29);
            this.button5.Name = "button5";
            this.button5.Size = new System.Drawing.Size(54, 46);
            this.button5.TabIndex = 11;
            this.button5.Text = "smart record";
            this.button5.UseVisualStyleBackColor = true;
            this.button5.Click += new System.EventHandler(this.button5_Click);
            // 
            // textBox3
            // 
            this.textBox3.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            this.textBox3.Location = new System.Drawing.Point(52, 257);
            this.textBox3.Name = "textBox3";
            this.textBox3.Size = new System.Drawing.Size(354, 20);
            this.textBox3.TabIndex = 7;
            // 
            // groupBox2
            // 
            this.groupBox2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            this.groupBox2.Controls.Add(this.label3);
            this.groupBox2.Controls.Add(this.label2);
            this.groupBox2.Controls.Add(this.treeView1);
            this.groupBox2.Controls.Add(this.textBox3);
            this.groupBox2.Controls.Add(this.textBox4);
            this.groupBox2.Location = new System.Drawing.Point(12, 136);
            this.groupBox2.Name = "groupBox2";
            this.groupBox2.Size = new System.Drawing.Size(418, 289);
            this.groupBox2.TabIndex = 8;
            this.groupBox2.TabStop = false;
            this.groupBox2.Text = "last result";
            // 
            // label3
            // 
            this.label3.AutoSize = true;
            this.label3.Location = new System.Drawing.Point(9, 41);
            this.label3.Name = "label3";
            this.label3.Size = new System.Drawing.Size(77, 13);
            this.label3.TabIndex = 15;
            this.label3.Text = "best responce:";
            // 
            // label2
            // 
            this.label2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left)));
            this.label2.AutoSize = true;
            this.label2.Location = new System.Drawing.Point(9, 260);
            this.label2.Name = "label2";
            this.label2.Size = new System.Drawing.Size(38, 13);
            this.label2.TabIndex = 14;
            this.label2.Text = "JSON:";
            // 
            // treeView1
            // 
            this.treeView1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
                        | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            this.treeView1.Location = new System.Drawing.Point(6, 74);
            this.treeView1.Name = "treeView1";
            this.treeView1.Size = new System.Drawing.Size(400, 170);
            this.treeView1.TabIndex = 8;
            // 
            // textBox4
            // 
            this.textBox4.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            this.textBox4.Enabled = false;
            this.textBox4.Location = new System.Drawing.Point(104, 29);
            this.textBox4.Multiline = true;
            this.textBox4.Name = "textBox4";
            this.textBox4.Size = new System.Drawing.Size(302, 39);
            this.textBox4.TabIndex = 10;
            // 
            // comboBox1
            // 
            this.comboBox1.FormattingEnabled = true;
            this.comboBox1.Items.AddRange(new object[] {
            "pl",
            "en-GB",
            "en-US",
            "de"});
            this.comboBox1.Location = new System.Drawing.Point(79, 54);
            this.comboBox1.Name = "comboBox1";
            this.comboBox1.Size = new System.Drawing.Size(121, 21);
            this.comboBox1.TabIndex = 12;
            // 
            // label1
            // 
            this.label1.AutoSize = true;
            this.label1.Location = new System.Drawing.Point(76, 29);
            this.label1.Name = "label1";
            this.label1.Size = new System.Drawing.Size(27, 13);
            this.label1.TabIndex = 13;
            this.label1.Text = "lang";
            // 
            // groupBox1
            // 
            this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            this.groupBox1.Controls.Add(this.button5);
            this.groupBox1.Controls.Add(this.comboBox1);
            this.groupBox1.Controls.Add(this.label1);
            this.groupBox1.Location = new System.Drawing.Point(13, 24);
            this.groupBox1.Name = "groupBox1";
            this.groupBox1.Size = new System.Drawing.Size(418, 100);
            this.groupBox1.TabIndex = 9;
            this.groupBox1.TabStop = false;
            this.groupBox1.Text = "recording";
            // 
            // microphone
            // 
            this.ClientSize = new System.Drawing.Size(453, 439);
            this.Controls.Add(this.groupBox1);
            this.Controls.Add(this.groupBox2);
            this.Name = "microphone";
            this.Text = "google speech-api";
            this.Load += new System.EventHandler(this.microphone_Load);
            this.groupBox2.ResumeLayout(false);
            this.groupBox2.PerformLayout();
            this.groupBox1.ResumeLayout(false);
            this.groupBox1.PerformLayout();
            this.ResumeLayout(false);

        }
        #endregion

      

       

        static Google_Speech.SpeechInputResult SR;
        /// <summary>
        /// rozpoznaj polecenie z pliki audio(.flac)
        /// </summary>
        /// <param name="flac_FileName">plik flac z daymi audio</param>
        private bool RecognizeCommand(string flac_FileName)
        {
            try
            {
                SR =
                Google_Speech.ProcessFlacFile(flac_FileName, 16000, LANGUAGE, 10);
            }
            catch (Exception e)
            {
                Debug.Fail("RecognizeCommand() " + e.Message);
            }


            //FAIL!
            if(SR==null || SR.hypotheses.Count()==0)
            {
                textBox4.Text = "fail";
                textBox4.ForeColor = System.Drawing.Color.DarkRed;
                treeView1.Nodes.Clear();
                return false;
            }

            //SUCES
            textBox4.ForeColor = System.Drawing.Color.DarkGreen;


            //RAW JSON
            textBox3.Text = SR.json_mem;
            //---

            //textBox nodes
            //-------------------
                treeView1.Nodes.Clear();
            
                List<TreeNode> l = new List<TreeNode>();

                l.Add(new TreeNode("staus: " + SR.status));

                l.Add(new TreeNode("id: " + SR.ID));

                List<TreeNode> l2 = new List<TreeNode>();
                foreach (Google_Speech.SpeechInputResult.Hypothesis h in SR.hypotheses)
                {
                    l2.Add(new TreeNode(h.ToString()));
                }
                l.Add(new TreeNode("hypothese (" + SR.hypotheses.Count() + ")", l2.ToArray()));

                TreeNode treeNode = new TreeNode("Google speech-api response", l.ToArray());

                treeView1.Nodes.Add(treeNode);

                treeView1.ExpandAll();
            //-------------------


            //best responese
                textBox4.Text = SR.getBestHypothesis().utterance + "@" + 100.0 * SR.getBestHypothesis().confidence + "%";

                switch (SR.status)
                {
                    case 0:
                        treeView1.BackColor = System.Drawing.Color.GreenYellow;
                        break;

                    case 5:
                        treeView1.BackColor = System.Drawing.Color.PaleVioletRed;
                        break;

                    default:
                        MessageBox.Show("WTF?! zły status");
                        break;
                }
            //------------------
                    

            return true;
        }

      
        /// <summary>
        /// rozpoczynamy rozpoznawanie
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void button3_Click(object sender, EventArgs e)
        {
            //zmien WAV - na flac
            sox.Convert(TMP_WAVFILENAME, TMP_FLACFILENAME);

            //zinterpretuj FLAC
            RecognizeCommand(TMP_FLACFILENAME);//rozpoznaj polecenie

            if (SR == null) return;
            Google_Speech.SpeechInputResult.Hypothesis
            h = SR.getBestHypothesis();
            
            switch (SR.status)
            {
                case 0://OK
                    MessageBox.Show("OK");
                    break;

                case 5://błąd!
                    MessageBox.Show("OK");
                    break;

                default:
                    MessageBox.Show("wrong status");
                    break;
            }
            
        }

        //OPEN FLAC AUDIO FILE
        private void button4_Click(object sender, EventArgs e)
        {
            ExecuteCommandSync(TMP_FLACFILENAME);//OPEN FLAC AUDIO FILE
        }

            void SayPL(string text)
            {
                try{
                    string tmp_mp3 = "a.mp3";
                    if (IsFileLocked(tmp_mp3)) tmp_mp3 = "a1.mp3";

                    Google_Speech.Say(text, tmp_mp3, "pl");
                    ExecuteCommandSync(tmp_mp3);   
                }
                catch (Exception ex)
                {
                    Debug.WriteLine(ex.Message);
                }
            }
            

            #region tools
            protected static bool IsFileLocked(string path)
            {
                FileInfo file = new FileInfo(path);
                FileStream stream = null;

                try
                {
                    stream = file.Open(FileMode.Open, FileAccess.ReadWrite, FileShare.None);
                }
                catch (IOException)
                {
                    //the file is unavailable because it is:
                    //still being written to
                    //or being processed by another thread
                    //or does not exist (has already been processed)
                    return true;
                }
                finally
                {
                    if (stream != null)
                        stream.Close();
                }

                //file is not locked
                return false;
            }


            /// <summary>
            /// Executes a shell command synchronously.
            /// </summary>
            /// <param name="command">string command</param>
            /// <returns>string, as output of the command.</returns>
            public static void ExecuteCommandSync(object command)
            {
                try
                {
                    // create the ProcessStartInfo using "cmd" as the program to be run,
                    // and "/c " as the parameters.
                    // Incidentally, /c tells cmd that we want it to execute the command that follows,
                    // and then exit.
                    System.Diagnostics.ProcessStartInfo procStartInfo =
                        new System.Diagnostics.ProcessStartInfo("cmd", "/c " + command);

                    // The following commands are needed to redirect the standard output.
                    // This means that it will be redirected to the Process.StandardOutput StreamReader.
                    procStartInfo.RedirectStandardOutput = true;
                    procStartInfo.UseShellExecute = false;
                    // Do not create the black window.
                    procStartInfo.CreateNoWindow = true;
                    // Now we create a process, assign its ProcessStartInfo and start it
                    System.Diagnostics.Process proc = new System.Diagnostics.Process();
                    proc.StartInfo = procStartInfo;
                    proc.Start();
                    // Get the output into a string
                    string result = proc.StandardOutput.ReadToEnd();
                    // Display the command output.
                    Console.WriteLine(result);
                }
                catch (Exception)
                {
                    // Log the exception
                }
            }
            #endregion

            private void button5_Click(object sender, EventArgs e)
            {
                TimeSpan ts = SOX.Execute(@"C:\Program Files (x86)\sox-14-4-0\rec.exe",
                            "C:\\a.wav"+
                            " silence 1 0.5 0.5% 1 0.5 1.0%"+
                            " -r 16000 -b 16 -c 1 ",10000);
                
                    double time = Math.Round(ts.TotalMilliseconds/1000.0,2);

                    MessageBox.Show("nagrano " + time + "s");

                    if (time < 2)
                    {
                        MessageBox.Show("za malo!");
                    }else{

                        SOX.Execute(@"C:\Program Files (x86)\sox-14-4-0\rec.exe",
                            TMP_WAVFILENAME + " " + TMP_FLACFILENAME + " --norm=-3 silence 1 0.5 0.5%",
                        10 * 1000);

                        RecognizeCommand(TMP_FLACFILENAME);
                    }
            }

            private void microphone_Load(object sender, EventArgs e)
            {
                comboBox1.Text = comboBox1.Items[0].ToString();

                string SOX_DIR = @"C:\Program Files (x86)\sox-14-4-0";

                while (sox == null)
                {
                    try{
                        sox = new SOX(SOX_DIR);
                    }catch(Exception e2)  
                    {
                        sox = null;
                        MessageBox.Show(e2.Message,"sox load fail",MessageBoxButtons.OK,MessageBoxIcon.Warning);       
                    }

                    if(sox==null)
                    {
                        if (MessageBox.Show("musisz mieć zainstalowany sox\n\n http://sox.sourceforge.net/ \n\ninstal sox & click ok", "download sox!", MessageBoxButtons.OKCancel, MessageBoxIcon.Stop)
                            ==
                            DialogResult.Cancel)
                        {
                            Environment.Exit(-1);
                        }

                        using (FolderBrowserDialog dialog = new FolderBrowserDialog())
                        {
                            dialog.Description = "Open a folder which contains SOX (sox.exe file)!";
                            dialog.ShowNewFolderButton = false;
                            dialog.RootFolder = Environment.SpecialFolder.MyComputer;
                            if (dialog.ShowDialog() == DialogResult.OK)
                            {
                                SOX_DIR = dialog.SelectedPath;
                            }
                        }
                    }
                }
            }
    }
}


